using System;
using System.Collections.Generic;
using System.Text;

using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;

using Athena.Core;

namespace Athena.Objects
{
    [Serializable()]
    public class RbsGlyph : PartGlyph
    {
        /// <summary>
        /// Initializes a new instance of the RBS class.
        /// </summary>
        /// <param name="location"></param>
        public RbsGlyph(PointF location)
        {
            TextH = HorizontalAlignment.Center;
            TextV = VerticalAlignment.BelowBottom;
            _Dimensions = new SizeF(60, 46);
            _oFillColorStart = Color.White;
            _oFillColorEnd = Color.SteelBlue;
            _oPartColor = Color.DeepSkyBlue;
            _oEdgeColor = Color.Black;

            //gene glyph points to a gene
            Item =new Part("rbs","RBS_0","ATTAAAGAGGAGAAA");

            _Location = location;
        }
        public RbsGlyph()
        {
            TextH = HorizontalAlignment.Center;
            TextV = VerticalAlignment.BelowBottom;
            _Location = new PointF(0, 0);
            _Dimensions = new SizeF(40, 40);
            Name = "RBS_0";
            _oPartColor = Color.DeepSkyBlue;
            _oEdgeColor = Color.Black;
            _Item = new Part("RBS", "rbs", "");
        }

        public override object Clone()
        {
            return new RbsGlyph(this);
        }

        public RbsGlyph(RbsGlyph copy) : base(copy)
        {

        }

        public override bool HasPreview
        {
            get
            {
                return true;
            }
        }

        public override Bitmap GetPreview(int width, int height)
        {
            Bitmap oBitmap = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(oBitmap);

            RenderIcon(g, width, height);

            return oBitmap;
        }

        static GraphicsPath _oBlockPath = CreateBlockPath(), _oPathShine = ShiningLine();

        static GraphicsPath CreateSchematicPath(float w, float h)
        {
            GraphicsPath oPath = new GraphicsPath();

            oPath.AddLine(0f, h, w + 1, h);

            return oPath;
        }

        static GraphicsPath CreateBlockPath()
        {
            GraphicsPath oPath = new GraphicsPath();

            oPath.AddEllipse(0, 0, 15, 10);
            
            oPath.CloseFigure();

            return oPath;
        }

        static GraphicsPath ShiningLine()
        {
            GraphicsPath oPath = new GraphicsPath();

            oPath.AddArc(1, 1, 10, 7.5f, 180, 90);

            return oPath;
        }


        public override void RenderGlyph(Graphics g)
        {
            Pen oOutline = new Pen(_oEdgeColor, _dEdgeThickness);
            Brush oFilled = new SolidBrush(_oPartColor);
            //Brush oFilled = new LinearGradientBrush(Location, new PointF(Location.X + Dimensions.Width, Location.Y + Dimensions.Height), Color.White, _oFillColor);

            GraphicsPath oPath;
            float w, h;

            switch (View)
            {
                case ViewType.Schematic:
                    w = _Dimensions.Width;
                    h = _Dimensions.Height;
                    oPath = (GraphicsPath)CreateSchematicPath(w+5, h);
                    break;
                default:
                    DrawBox(g);
                    oPath = (GraphicsPath)_oBlockPath.Clone();
                    w = h = 0.5f * Math.Min(_Dimensions.Height, _Dimensions.Width);
                    break;
            }

            RectangleF pathBounds = oPath.GetBounds();

            Matrix oTransform = new Matrix();

            if (Direction == Part.Orientation.forward)
            {
                if (View != ViewType.Schematic)
                {
                    oTransform.Scale(
                         w / pathBounds.Width,
                         h / pathBounds.Height, MatrixOrder.Prepend);
                }
                oTransform.Translate(
                    0.5f * _Dimensions.Width + _Location.X - w / 2,
                    0.5f * _Dimensions.Height + _Location.Y - h / 2,
                    MatrixOrder.Append);
            }
            else
            {
                if (View != ViewType.Schematic)
                {
                    oTransform.Scale(
                       -w / pathBounds.Width,
                         h / pathBounds.Height, MatrixOrder.Prepend);
                }
                else
                {
                    oTransform.Scale(-1, 1, MatrixOrder.Prepend);
                }
                oTransform.Translate(
                    0.5f * _Dimensions.Width + _Location.X + w / 2,
                    0.5f * _Dimensions.Height + _Location.Y - h / 2,
                    MatrixOrder.Append);
            }

            oPath.Transform(oTransform);

            if (View == ViewType.Schematic)
                g.FillPath(new SolidBrush(_oFillColorEnd), oPath);

            g.DrawPath(oOutline, oPath);

            if (View == ViewType.Block)
            {
                GraphicsPath oPathShine = (GraphicsPath)_oPathShine.Clone();
                oPathShine.Transform(oTransform);
                g.FillPath(oFilled, oPath);
                g.DrawPath(new Pen(Color.White, w / 20), oPathShine);
            }
        }
        public override SBMLExtension.EmlRenderExtension.LocalStyle ToStyle(SBMLExtension.EmlRenderExtension.RenderInformation oInfo)
        {

            SBMLExtension.EmlRenderExtension.LocalStyle oResult = new SBMLExtension.EmlRenderExtension.LocalStyle();
            SBMLExtension.EmlRenderExtension.Group oGroup = new SBMLExtension.EmlRenderExtension.Group();
            oGroup.Stroke = oInfo.AddColorDefinition(_oEdgeColor);
            oGroup.StrokeWidth = _dEdgeThickness.ToString();
            if (_oFillColorStart == _oFillColorEnd)
                oGroup.Fill = oInfo.AddColorDefinition(_oFillColorStart);
            else
                oGroup.Fill = oInfo.AddLinearGradientDefinition(_oFillColorStart, _oFillColorEnd);


            oGroup.Children.Add(new SBMLExtension.EmlRenderExtension.Rectangle());

            SBMLExtension.EmlRenderExtension.Ellipses oEllipse = new SBMLExtension.EmlRenderExtension.Ellipses(10.0, 10.0);
            oEllipse.Fill = oInfo.AddColorDefinition(PartColor);
            // HACK: THIS IS NOT THE RIGHT THING TO DO 
            oEllipse.CX = (Bounds.Width/2f).ToString() ;
            oEllipse.CY = (Bounds.Height/2f).ToString();
            oEllipse.Stroke = oGroup.Stroke;
            oEllipse.StrokeWidth = oGroup.StrokeWidth;
            oGroup.Children.Add(oEllipse);


            if (!string.IsNullOrEmpty(Text) && ShowText)
            {
                SBMLExtension.EmlRenderExtension.Text oText = new SBMLExtension.EmlRenderExtension.Text();
                oText.FontFamily = TextFont.FontFamily.Name;
                oText.FontSize = TextFont.SizeInPoints.ToString();
                oText.Stroke = oInfo.AddColorDefinition(TextColor);
                if (TextFont.Bold) oText.FontWeight = SBMLExtension.EmlRenderExtension.Text.FontWeiths.bold.ToString();
                if (TextFont.Italic) oText.FontStyle = SBMLExtension.EmlRenderExtension.Text.FontStyles.italic.ToString();
                oText.StrokeWidth = "1";
                oText.Y = "130%";
                oText.X = "-50%";
                oText.TheText = Text;
                oGroup.Children.Add(oText);
            }
            oResult.Group = oGroup;
            return oResult;
        }

        public override void RenderIcon(Graphics g, float width, float height)
        {
            Pen oOutline = new Pen(_oEdgeColor, 0.5f);
            Brush oFilled = new SolidBrush(_oPartColor);

            //g.FillRectangle(new SolidBrush(Color.Snow), 0, 0, width, height);

            GraphicsPath oPath = (GraphicsPath)_oBlockPath.Clone();
            GraphicsPath oPathShine = (GraphicsPath)_oPathShine.Clone();

            RectangleF pathBounds = _oBlockPath.GetBounds();

            Matrix oTransform = new Matrix();

            oTransform.Scale(
                   0.7f * width / pathBounds.Width,
                   0.7f * height / pathBounds.Height, MatrixOrder.Prepend);
            oTransform.Translate(2f, 2f);

            oPath.Transform(oTransform);
            oPathShine.Transform(oTransform);

            g.FillPath(oFilled, oPath);
            g.DrawPath(oOutline, oPath);
            g.DrawPath(new Pen(Color.White, 1), oPathShine);
        }
    }
}
